package com.okilo.online.app.weight.font

import android.content.Context
import android.graphics.Color
import android.graphics.LinearGradient
import android.graphics.Shader
import android.graphics.Typeface
import android.util.AttributeSet
import android.util.LruCache
import androidx.appcompat.widget.AppCompatTextView
import androidx.core.content.withStyledAttributes
import com.okilo.online.app.R

class OkiloTextView @JvmOverloads constructor (
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : AppCompatTextView(context, attrs, defStyleAttr) {

    companion object {
        private const val FONT_RBT_BLACK = "fonts/Rbt-Black.ttf"
        private const val FONT_RBT_BLACKITALIC = "fonts/Rbt-BlackItalic.ttf"
        private const val FONT_RBT_BOLD = "fonts/Rbt-Bold.ttf"
        private const val FONT_RBT_MEDIUM = "fonts/Rbt-Medium.ttf"
        private const val FONT_RBT_REGULAR = "fonts/Rbt-Regular.ttf"
        private const val FONT_RBT_SEMIBOLD = "fonts/Rbt-SemiBold.ttf"

        // 字体缓存
        private val typefaceCache = mutableMapOf<String, Typeface>()

        // 渐变缓存 - 避免重复创建
        private val gradientCache = LruCache<String, LinearGradient>(20)
    }

    enum class FontType {
        RBT_BLACK, RBT_BLACKITALIC, RBT_BOLD, RBT_MEDIUM, RBT_REGULAR, RBT_SEMIBOLD, CUSTOM
    }

    enum class GradientDirection {
        LEFT_TO_RIGHT, TOP_TO_BOTTOM, TOP_LEFT_TO_BOTTOM_RIGHT, BOTTOM_LEFT_TO_TOP_RIGHT
    }

    // 使用基本数据类型减少内存占用
    private var fontType: FontType = FontType.RBT_MEDIUM
    private var customFontPath: String? = null
    private var enableGradient: Boolean = false
    private var gradientDirection: GradientDirection = GradientDirection.LEFT_TO_RIGHT

    // 延迟初始化的颜色字段
    private var startColor: Int = 0
    private var endColor: Int = 0
    private var centerColor: Int? = null

    // 状态标志，避免不必要的重绘
    private var isGradientDirty: Boolean = true
    private var lastGradientKey: String? = null

    init {
        initAttributes(attrs)
    }

    private fun initAttributes(attrs: AttributeSet?) {
        context.withStyledAttributes(attrs, R.styleable.OkiloTextView) {
            // 快速读取属性
            fontType = FontType.entries.toTypedArray().getOrElse(
                getInt(R.styleable.OkiloTextView_fontType, FontType.RBT_MEDIUM.ordinal)
            ) { FontType.RBT_MEDIUM }

            customFontPath = getString(R.styleable.OkiloTextView_customFontPath)
            enableGradient = getBoolean(R.styleable.OkiloTextView_enableGradient, false)

            // 只有当启用渐变时才读取颜色属性
            if (enableGradient) {
                startColor = getColor(R.styleable.OkiloTextView_startColor, currentTextColor)
                endColor = getColor(R.styleable.OkiloTextView_endColor, currentTextColor)
                centerColor = if (hasValue(R.styleable.OkiloTextView_centerColor)) {
                    getColor(R.styleable.OkiloTextView_centerColor, Color.TRANSPARENT)
                } else {
                    null
                }

                gradientDirection = when (getInt(R.styleable.OkiloTextView_gradientDirection, 0)) {
                    1 -> GradientDirection.TOP_TO_BOTTOM
                    2 -> GradientDirection.TOP_LEFT_TO_BOTTOM_RIGHT
                    3 -> GradientDirection.BOTTOM_LEFT_TO_TOP_RIGHT
                    else -> GradientDirection.LEFT_TO_RIGHT
                }
            }
        }

        setCustomFont()
    }

    override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
        super.onLayout(changed, left, top, right, bottom)
        // 只有启用渐变且布局变化时才应用渐变
        if (enableGradient && changed) {
            applyGradient()
        }
    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        // 尺寸变化时标记渐变需要更新
        if (enableGradient && (w != oldw || h != oldh)) {
            isGradientDirty = true
        }
    }

    private fun setCustomFont() {
        val fontPath = when (fontType) {
            FontType.CUSTOM -> customFontPath
            else -> getFontPath(fontType)
        } ?: return

        val typeface = getCachedTypeface(fontPath)
        typeface?.let { setTypeface(it) }
    }

    private fun getCachedTypeface(fontPath: String): Typeface? {
        // 检查缓存
        typefaceCache[fontPath]?.let { return it }
        // 加载字体
        return try {
            val typeface = Typeface.createFromAsset(context.assets, fontPath)
            typefaceCache[fontPath] = typeface
            typeface
        } catch (e: Exception) {
            e.printStackTrace()
            null
        }
    }

    private fun getFontPath(fontType: FontType): String? {
        return when (fontType) {
            FontType.RBT_BLACK -> FONT_RBT_BLACK
            FontType.RBT_BLACKITALIC -> FONT_RBT_BLACKITALIC
            FontType.RBT_BOLD -> FONT_RBT_BOLD
            FontType.RBT_MEDIUM -> FONT_RBT_MEDIUM
            FontType.RBT_REGULAR -> FONT_RBT_REGULAR
            FontType.RBT_SEMIBOLD -> FONT_RBT_SEMIBOLD
            FontType.CUSTOM -> null
        }
    }

    private fun applyGradient() {
        if (!enableGradient) {
            paint.shader = null
            return
        }

        if (!isGradientDirty) return

        val gradientKey = buildGradientKey()
        if (gradientKey == lastGradientKey) {
            isGradientDirty = false
            return
        }

        var gradient = gradientCache.get(gradientKey)
        if (gradient == null) {
            gradient = createLinearGradient()
            gradientCache.put(gradientKey, gradient)
        }

        paint.shader = gradient
        lastGradientKey = gradientKey
        isGradientDirty = false
    }

    private fun buildGradientKey(): String {
        return "${width}x${height}_${gradientDirection}_$startColor-$endColor-${centerColor ?: "none"}"
    }

    private fun createLinearGradient(): LinearGradient {
        val colors = if (centerColor != null) {
            intArrayOf(startColor, centerColor!!, endColor)
        } else {
            intArrayOf(startColor, endColor)
        }

        val (x0, y0, x1, y1) = when (gradientDirection) {
            GradientDirection.TOP_TO_BOTTOM ->
                GradientPoints(0f, 0f, 0f, height.toFloat())
            GradientDirection.TOP_LEFT_TO_BOTTOM_RIGHT ->
                GradientPoints(0f, 0f, width.toFloat(), height.toFloat())
            GradientDirection.BOTTOM_LEFT_TO_TOP_RIGHT ->
                GradientPoints(0f, height.toFloat(), width.toFloat(), 0f)
            else -> // LEFT_TO_RIGHT
                GradientPoints(0f, 0f, width.toFloat(), 0f)
        }

        return LinearGradient(x0, y0, x1, y1, colors, null, Shader.TileMode.CLAMP)
    }

    // ============ 公共方法 ============

    fun setFontType(type: FontType) {
        if (this.fontType == type) return
        this.fontType = type
        this.customFontPath = null
        setCustomFont()
    }

    fun setCustomFont(fontPath: String) {
        this.fontType = FontType.CUSTOM
        this.customFontPath = fontPath
        setCustomFont()
    }

    fun setEnableGradient(enable: Boolean) {
        if (this.enableGradient == enable) return
        this.enableGradient = enable
        isGradientDirty = true
        if (enable) {
            applyGradient()
        } else {
            paint.shader = null
            lastGradientKey = null
        }
    }

    fun setGradientColors(startColor: Int, endColor: Int) {
        this.startColor = startColor
        this.endColor = endColor
        this.centerColor = null
        this.enableGradient = true
        isGradientDirty = true
        applyGradient()
    }

    fun setGradientDirection(direction: GradientDirection) {
        if (this.gradientDirection == direction) return
        this.gradientDirection = direction
        if (enableGradient) {
            isGradientDirty = true
            applyGradient()
        }
    }

    private data class GradientPoints(val x0: Float, val y0: Float, val x1: Float, val y1: Float)

}